import { IRenderMessage, IRenderReplyMessage, messageMagic } from '../declare/Message'

export interface IEventHandler<P, R> {
    handle(messageId: string, params?: P): IRenderReplyMessage<R>
}

export class RenderMsg {
    private ipcMain: Electron.IpcMain
    private webContent: Electron.WebContents
    private readonly handlers: Map<string, Handler>

    listener = async (event, data) => {
        try {
            const params = JSON.parse(data) as IRenderMessage<unknown>
            const handler = this.handlers.get(params.eventType)
            if (handler) {
                new Promise((resolve, reject) => {
                    try {
                        const result = handler.handle(params.messageId, params.data)
                        const data = JSON.stringify(result)
                        event.reply(messageMagic, data)
                        resolve(data)
                    } catch (error) {
                        reject(error)
                    }
                })
            } else {
                throw new Error('Unknown event handler:' + data)
            }
        } catch (e) {
            console.error(e)
        }
    }

    public registerHandler = (handlerName: string | EventType, handler: IEventHandler) => {
        this.handlers.set(handlerName, handler)
    }

    public unregisterHandler = (handlerName: string | EventType) => {
        this.handlers.delete(handlerName)
    }

    constructor() {
        this.handlers = new Map<string, IEventHandler>()
    }

    public setWebContent(content: Electron.WebContents): RenderMsg {
        this.webContent = content
        return this
    }

    public setIpcMain(ipcMain: Electron.IpcMain): RenderMsg {
        this.ipcMain = ipcMain
        this.ipcMain.on(messageMagic, this.listener)
        return this
    }
}

const renderMsg = new RenderMsg()
export default renderMsg
